package com.mazaiting.redeye.utils.confuse;
import com.mazaiting.redeye.utils.StreamUtil;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;

/**
 * OpenSSL 公私钥工具类
 */
public class OpensslUtil {
    /**
     * 私钥文件名
     */
    private static final String PRIVATE_KEY_FILE_NAME = "rsa_1024_priv.pem";
    /**
     * PKCS8 编码后的私钥
     */
    private static final String PRIVATE_KEY_FILE_NAME_PKCS8 = "pkcs8_rsa_private_key.pem";
    /**
     * 公钥文件名
     */
    private static final String PUBLIC_KEY_FILE_NAME = "rsa_1024_pub.pem";
    /**
     * 查看版本信息命令
     */
    private static final String VERSION = "openssl version -v";
    /**
     * 生成私钥
     */
    private static final String GENERATE_PRIVATE_KEY = "openssl genrsa -out " + PRIVATE_KEY_FILE_NAME + " 1024";
    /**
     * 生成公钥
     */
    private static final String GENERATE_PUBLIC_KEY =
            "openssl rsa -pubout -in " + PRIVATE_KEY_FILE_NAME + " -out " + PUBLIC_KEY_FILE_NAME;
    /**
     * 查看私钥
     */
    private static final String CAT_PRIVATE_KEY = "cat " + PRIVATE_KEY_FILE_NAME;
    /**
     * 查看 PKCS8 编码后的私钥
     */
    private static final String CAT_PRIVATE_KEY_PKCS8 = "cat " + PRIVATE_KEY_FILE_NAME_PKCS8;
    /**
     * 查看公钥
     */
    private static final String CAT_PUBLIC_KEY = "cat " + PUBLIC_KEY_FILE_NAME;
    /**
     * PKCS8 编码
     */
    private static final String PKCS8_ENCODER = "openssl pkcs8 -topk8 -inform PEM -in " + PRIVATE_KEY_FILE_NAME +
            " -outform PEM -out " + PRIVATE_KEY_FILE_NAME_PKCS8 + " -nocrypt";

    /**
     * 获取 OpenSSL 版本
     * @return OpenSSL 版本
     */
    public static String getVersion() {
        return runCommand(VERSION);
    }

    /**
     * 获取 RSA 私钥
     * 生成路径 : 在项目的根目录下, red_eye_server/rsa_1024_priv.pem
     * 生成文件名 : rsa_1024_priv.pem
     */
    public static String generatePrivateKey() {
        return runCommand(GENERATE_PRIVATE_KEY);
    }

    /**
     * 查看私钥
     * @return 私钥
     */
    public static String catPrivateKey() {
        return runCommand(CAT_PRIVATE_KEY);
    }

    /**
     * 获取私钥
     * @return 私钥
     */
    public static String getPrivateKey() {
        // 私钥
        String privateKey = catPrivateKeyWithPkcs8();
        // 检测私钥长度是否大于 100
        if (privateKey.length() > 100) {
            // 取出头部与尾部
            privateKey = privateKey.substring(28, privateKey.length() - 26);
        }
        return privateKey;
    }

    /**
     * 将私钥进行 pkcs8 编码
     * @return pkcs8 编码后的私钥
     */
    public static String pkcs8Encoder() {
        return runCommand(PKCS8_ENCODER);
    }

    /**
     * 查看 PKCS8 编码后的私钥
     * @return PKCS8 编码后的私钥
     */
    public static String catPrivateKeyWithPkcs8() {
        return runCommand(CAT_PRIVATE_KEY_PKCS8);
    }

    /**
     * 生成公钥
     * @return 公钥
     */
    public static String generatePublicKey() {
        return runCommand(GENERATE_PUBLIC_KEY);
    }

    /**
     * 查看公钥
     * @return 公钥
     */
    public static String catPublicKey() {
        return runCommand(CAT_PUBLIC_KEY);
    }

    /**
     * 获取公钥
     * @return 私钥
     */
    public static String getPublicKey() {
        // 私钥
        String publicKey = catPublicKey();
        // 判断私钥铲毒是否大于100
        if (publicKey.length() > 100) {
            // 取出头部与尾部
            publicKey = publicKey.substring(27, publicKey.length() - 25);
        }
        return publicKey;
    }

    /**
     * 检测公钥或私钥是否有效
     * @param value 公钥或私钥
     * @return true: 有效; false: 无效
     */
    public static boolean isValid(String value) {
        // 标记是否有效
        boolean isValid = true;
        // 检测是否有效条件
        if (StringUtils.isEmpty(value) || "\n".equals(value)) {
            // 无效
            isValid = false;
        }
        return isValid;
    }

    /**
     * 运行命令
     * @param command 命令
     * @return 返回内容
     */
    private static String runCommand(String command) {
        String result = "";
        try {
            // 检测版本
            Process process = Runtime.getRuntime().exec(command);
            // 取得命令结果的输出流
            InputStream is = process.getInputStream();
            // 获取内容
            result = StreamUtil.getKeyString(is);
        } catch (IOException e) {
//            e.printStackTrace();
        }
        return result;
    }
}
